package com.xbts.common.utils;


import com.xbts.common.utils.bean.BeanUtils;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @Author llk
 * @Date 2023/8/30 16:38
 */
public class WordUtils {

    private static final Logger log = LoggerFactory.getLogger(WordUtils.class);

    /**
     * 生成word文件
     *
     * @param rClazz   用于替换的实体类
     * @param richText 富文本
     * @param list     用于替换的实体类集合
     * @param <T>      实体类
     * @param <R>      实体类
     * @return ByteArrayOutputStream word文件流
     */
    public static <T, R> ByteArrayOutputStream createWord(R rClazz, String richText, List<T> list) {
        // 1. 创建一个新的空白Word文档
        XWPFDocument document = new XWPFDocument();
        try {
            // 1. 解析HTML内容
            org.jsoup.nodes.Document htmlDoc = Jsoup.parse(richText);
            // 2. 创建一个空白的Word文档段落
            XWPFParagraph paragraph = document.createParagraph();
            // 3. 遍历HTML文档中的所有元素
            Elements elements = htmlDoc.body().children();

            Map<String, String> attributeValueMap = BeanUtils.getClassAttributeValue(rClazz);
            // key添加${}，方便替换
            if (attributeValueMap != null) {
                attributeValueMap = attributeValueMap.entrySet().stream().filter(f -> f.getValue() != null).collect(Collectors.toMap(entry -> "${" + entry.getKey() + "}", Map.Entry::getValue));
            }
            for (Element element : elements) {
                String text = element.text();
                // 4. 根据元素类型，创建对应的Word文档段落或其他内容
                if (element.tagName().equals("p")) {
                    // 创建段落
                    XWPFRun run = paragraph.createRun();
                    String html = element.html();// 保留html中的空格
                    String value = "";
                    Pattern pattern = Pattern.compile(".*\\$\\{.*}.*");
                    if (pattern.matcher(html).matches()) {
                        // 将html中的空格替换成空格
                        value = html.replace("&nbsp;", " ");
                    } else {
                        value = text;
                    }
                    run.setText(replaceParagraphPlaceholders(value, attributeValueMap));
                    if (element.children().size() > 0 && element.child(0).tagName().equals("strong")) {
                        run.setBold(true);
                        run.setFontSize(13);
                    }
                } else if (element.tagName().equals("h2")) {
                    // 创建标题
                    XWPFRun run = paragraph.createRun();
                    run.setText(replaceParagraphPlaceholders(text, attributeValueMap));
                    run.setBold(true);
                    run.setFontSize(16);
                    // 居中
                    paragraph.setAlignment(ParagraphAlignment.CENTER);
                } else if (element.tagName().equals("img")) {
                    // 创建图片
                    String imageUrl = element.attr("src");
                    InputStream imageStream = new FileInputStream(imageUrl);
                    BufferedImage bufferedImage = ImageIO.read(imageStream);
                    XWPFRun run = paragraph.createRun();
//                    run.addPicture(imageStream, XWPFDocument.PICTURE_TYPE_JPEG, "image.jpeg", Units.toEMU(200), Units.toEMU(200));
                    run.addPicture(imageStream, XWPFDocument.PICTURE_TYPE_JPEG, "image.jpeg", Units.toEMU(bufferedImage.getWidth()), Units.toEMU(bufferedImage.getHeight()));
                } else if (element.tagName().equals("table")) {
                    if (element.children().size() > 0 && element.child(0).tagName().equals("tbody")) {
                        // 创建表格
                        Element tbody = element.child(0);
                        Elements trs = tbody.children();
                        XWPFTable table = document.createTable(list.size() + 1, trs.get(0).childNodeSize()); // n+1行 1行为表头
                        // trs.get(0) 为表头  trs.get(1) 为表体
                        for (int i = 0; i < table.getRows().size(); i++) {
                            // 表头
                            if (i == 0) {
                                Element tr = trs.get(i);
                                Elements tds = tr.children();
                                for (int i1 = 0; i1 < tds.size(); i1++) {
                                    String tableText = tds.get(i1).text();
                                    XWPFTableCell xwpfTableCell = table.getRow(i).getCell(i1);
                                    xwpfTableCell.setWidth("5000");
                                    xwpfTableCell.setText(tableText);
                                }
                            // 表体
                            } else {
                                Element tr = trs.get(1);
                                Elements tds = tr.children();
                                for (int k = 0; k < list.size(); k++) {
                                    Map<String, String> classAttributeValue = BeanUtils.getClassAttributeValue(list.get(k));
                                    if (classAttributeValue != null) {
                                        classAttributeValue = classAttributeValue.entrySet().stream().filter(f -> f.getValue() != null).collect(Collectors.toMap(entry -> "${" + entry.getKey() + "}", Map.Entry::getValue));
                                    }
                                    for (int j = 0; j < tds.size(); j++) {
                                        String tableText = tds.get(j).text();
                                        tableText = replaceParagraphPlaceholders(tableText, classAttributeValue);
                                        XWPFTableCell xwpfTableCell = table.getRow(i + k).getCell(j);
                                        if(StringUtils.isNotNull(xwpfTableCell)){
                                            xwpfTableCell.setWidth("5000");
                                            xwpfTableCell.setText(tableText);
                                        }
                                    }
                                }
                                break;
                            }
                        }
                    }
                }
                // 换行
                paragraph = document.createParagraph();
            }
            // 5. 将Word文档写入到输出流中
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            document.write(outputStream);
            outputStream.close();
            return outputStream;
        } catch (Exception e) {
            log.error("生成word文档失败", e);
        }
        return null;
    }

    /**
     * 替换段落中的占位符
     *
     * @param value               段落内容
     * @param classAttributeValue 占位符对应的值
     * @return 替换后的段落内容
     */
    private static String replaceParagraphPlaceholders(String value, Map<String, String> classAttributeValue) {
        Pattern pattern = Pattern.compile(".*\\$\\{.*}.*");
        if (pattern.matcher(value).matches()) {
            for (Map.Entry<String, String> entry : classAttributeValue.entrySet()) {
                value = value.replace(entry.getKey(), entry.getValue());
            }
            // 处理没有被替换的字符串
            if (pattern.matcher(value).matches()) {
                // 正则替换未被替换的字符串并设置为空
                value = value.replaceAll("\\$\\{.*?\\}", "");
            }
        }
        return value;
    }

    private static void insertPictureInTableCell(XWPFDocument document, String placeholder, String picturePath) throws Exception {
        List<XWPFTable> tables = new ArrayList<>(document.getTables());
        for (XWPFTable table : tables) {
            List<XWPFTableRow> rows = new ArrayList<>(table.getRows());
            for (XWPFTableRow row : rows) {
                List<XWPFTableCell> cells = new ArrayList<>(row.getTableCells());
                for (XWPFTableCell cell : cells) {
                    List<XWPFParagraph> paragraphs = new ArrayList<>(cell.getParagraphs());
                    for (XWPFParagraph paragraph : paragraphs) {
                        List<XWPFRun> runs = new ArrayList<>(paragraph.getRuns());
                        for (XWPFRun run : runs) {
                            String text = run.getText(0);
                            if (text != null && text.contains(placeholder)) {
                                int index = text.indexOf(placeholder);
                                if (index >= 0) {
                                    // 移除占位符
                                    run.setText(text.replace(placeholder, ""), 0);

                                    // 在当前段落中插入图片
                                    XWPFRun pictureRun = paragraph.createRun();
                                    try (FileInputStream pictureInputStream = new FileInputStream(picturePath)) {
                                        pictureRun.addPicture(pictureInputStream, Document.PICTURE_TYPE_JPEG, "picture.jpg", Units.toEMU(200), Units.toEMU(200));
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
